package com.strato.quartz.v1_0_0.schedule;

import org.quartz.SchedulerException;
import org.quartz.impl.DirectSchedulerFactory;
import org.quartz.impl.jdbcjobstore.InvalidConfigurationException;
import org.quartz.impl.jdbcjobstore.JobStoreTX;
import org.quartz.simpl.RAMJobStore;
import org.quartz.simpl.SimpleThreadPool;
import org.quartz.spi.JobStore;
import org.quartz.utils.DBConnectionManager;

import com.strato.quartz.v1_0_0.schedule.impl.QuartzScheduler;
import com.strato.quartz.v1_0_0.schedule.jobstore.JobStoreConfig;
import com.strato.quartz.v1_0_0.schedule.jobstore.JobStoreTxConfig;
import com.strato.quartz.v1_0_0.schedule.jobstore.RamStoreConfig;
import com.strato.quartz.v1_0_0.schedule.jobstore.tx.DataSourceConnectionProvider;

public class SchedulerFactory {

	private static SchedulerFactory instance=new SchedulerFactory();
	
	public static SchedulerFactory getInstance(){
		return instance;
	}
	
	public void createScheduler(String schedulerId,int threadCount){
		createScheduler(schedulerId, threadCount, null);
	}
	public void createScheduler(String schedulerId,int threadCount,JobStoreConfig jobStoreConfig){
		JobStore jobStore=createJobStore(schedulerId,jobStoreConfig);
		SimpleThreadPool threadPool=new SimpleThreadPool(threadCount, Thread.NORM_PRIORITY);
		try {
			DirectSchedulerFactory.getInstance().createScheduler(schedulerId, schedulerId, threadPool, jobStore);
		} catch (SchedulerException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	
	private JobStore createJobStore(String schedulerId, JobStoreConfig jobStoreConfig) {
		if(jobStoreConfig==null){
			jobStoreConfig=new RamStoreConfig();
		}
		if(RamStoreConfig.class.isInstance(jobStoreConfig)){
			RAMJobStore jobStore=new RAMJobStore();
			jobStore.setMisfireThreshold(jobStoreConfig.getMisfireThreshold());
			return jobStore;
		}else if(JobStoreTxConfig.class.isInstance(jobStoreConfig)){
			JobStoreTxConfig txConfig=(JobStoreTxConfig) jobStoreConfig;
			JobStoreTX jobStore=new JobStoreTX();
			String dataSourceName=txConfig.getDataSourceName();
			try {
				DataSourceConnectionProvider provider=new DataSourceConnectionProvider();
				provider.setDataSourceName(dataSourceName);
				DBConnectionManager.getInstance().addConnectionProvider(dataSourceName, provider);
				jobStore.setDataSource(dataSourceName);
				jobStore.setThreadsInheritInitializersClassLoadContext(true);
				jobStore.setDriverDelegateClass(txConfig.getDriverDelegateClass());
				jobStore.setMisfireThreshold(jobStoreConfig.getMisfireThreshold());
				jobStore.setTablePrefix(txConfig.getTablePrefix());
				return jobStore;
			} catch (InvalidConfigurationException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
			
		}
		throw new IllegalArgumentException("Unknown jobstore config:"+jobStoreConfig);
	}

	public Scheduler getScheduler(String schedulerId){
		try {
			org.quartz.Scheduler qscheduler = DirectSchedulerFactory.getInstance().getScheduler(schedulerId);
			if(qscheduler==null){
				return null;
			}
			return new QuartzScheduler(qscheduler);
		} catch (SchedulerException e) {
			e.printStackTrace();
			return null;
		}
	}
}
